home *** CD-ROM | disk | FTP | other *** search
/ Aminet 37 / Aminet 37 (2000)(Schatztruhe)[!][Jun 2000].iso / Aminet / dev / lang / sofa.lha / sofa / smalleiffel / lib_std / fixed_array3.e < prev    next >
Text File  |  2000-03-25  |  13KB  |  482 lines

  1. -- This file is  free  software, which  comes  along  with  SmallEiffel. This
  2. -- software  is  distributed  in the hope that it will be useful, but WITHOUT 
  3. -- ANY  WARRANTY;  without  even  the  implied warranty of MERCHANTABILITY or
  4. -- FITNESS  FOR A PARTICULAR PURPOSE. You can modify it as you want, provided
  5. -- this header is kept unaltered, and a notification of the changes is added.
  6. -- You  are  allowed  to  redistribute  it and sell it, alone or as a part of 
  7. -- another product.
  8. --          Copyright (C) 1994-98 LORIA - UHP - CRIN - INRIA - FRANCE
  9. --            Dominique COLNET and Suzanne COLLIN - colnet@loria.fr 
  10. --                       http://SmallEiffel.loria.fr
  11. --
  12. class FIXED_ARRAY3[E]
  13.    --   
  14.    -- Resizable three dimensional array.
  15.    -- Unlike ARRAY3, the `lower1', `lower2' and `lower3' bounds are 
  16.    -- frozen to 0. Thus, one can expect better performances.
  17.    --
  18.    -- Initially written by Jean-Philippe Caillaut in Mai 1999
  19.    --
  20.    
  21. inherit COLLECTION3[E];
  22.    
  23. creation
  24.    make, copy, from_collection3, from_collection, from_model
  25.    
  26. feature
  27.    
  28.    upper1, count1, upper2, count2, upper3, count3, count: INTEGER;
  29.    
  30. feature {NONE}
  31.  
  32.    count2x3: INTEGER;
  33.          -- To speed up access, this value is always equal to
  34.          -- `count2' * `count3'
  35.  
  36. feature {FIXED_ARRAY3}
  37.    
  38.    storage: NATIVE_ARRAY[E];
  39.    
  40.    capacity: INTEGER; -- of `storage'.
  41.  
  42. feature
  43.    
  44.    lower1: INTEGER is 0;      
  45.  
  46.    lower2: INTEGER is 0;      
  47.  
  48.    lower3: INTEGER is 0;
  49.       
  50.    make(new_count1, new_count2, new_count3 : INTEGER) is
  51.      -- Create or reset `Current' with new dimensions.
  52.      -- All elements are set to the default value of type E.
  53.       require
  54.      new_count1 > 0;
  55.          new_count2 > 0;
  56.          new_count3 > 0
  57.       do
  58.      count1 := new_count1;
  59.      upper1 := new_count1 - 1;
  60.      count2 := new_count2;
  61.      upper2 := new_count2 - 1;     
  62.          count3 := new_count3;
  63.          count2x3 := count2 * count3;
  64.          upper3 := new_count3 - 1;       
  65.          count := count1 * count2x3;
  66.      if capacity < count then
  67.         capacity := count;
  68.         storage := storage.calloc(capacity);
  69.      else
  70.         storage.clear_all(capacity - 1);
  71.      end;
  72.       ensure
  73.      count1 = new_count1;
  74.      count2 = new_count2;
  75.          count3 = new_count3;
  76.      all_default
  77.       end;
  78.    
  79.    from_collection3(model: COLLECTION3[like item]) is
  80.      -- Uses the `model' to update Current.
  81.       local
  82.          i, j, k: INTEGER;
  83.       do
  84.          make(model.upper1+1, model.upper2+1, model.upper3+1);
  85.      from
  86.         i := 0;
  87.      until
  88.         i > upper1
  89.      loop
  90.         from
  91.            j := 0;
  92.         until
  93.            j > upper2
  94.         loop
  95.                from
  96.                   k := 0;
  97.                until
  98.                   k > upper3
  99.                loop
  100.                   put(model.item(i,j,k),i,j,k);
  101.                   k := k + 1;
  102.                end
  103.            j := j + 1;
  104.         end
  105.         i := i + 1;
  106.      end
  107.       end;
  108.  
  109.    from_collection(contents: COLLECTION[E];
  110.         new_count1, new_count2, new_count3: INTEGER) is
  111.          --  Reset all bounds using `new_count#i'.
  112.      --  Copy all elements of `contents', line by line into Current.
  113.       require
  114.          new_count1 >= 0;
  115.          new_count2 >= 0;
  116.          new_count3 >= 0;
  117.          contents.count = new_count1 * new_count2 * new_count3
  118.       local
  119.          i: INTEGER;
  120.       do
  121.          make(new_count1, new_count2, new_count3);
  122.      from 
  123.         i := 0  
  124.      until
  125.         i >= count
  126.      loop
  127.         storage.put(contents.item(contents.lower + i),i);
  128.             i := i + 1;
  129.      end
  130.       ensure
  131.          line_maximum = new_count1 - 1;
  132.          column_maximum = new_count2 - 1;
  133.          depth_maximum = new_count3 - 1;
  134.          count = contents.count
  135.       end
  136.  
  137.    from_model(model: COLLECTION[COLLECTION[COLLECTION[E]]]) is
  138.          -- The `model' is used to fill line by line the COLLECTION3.
  139.          -- Assume all sub-collections of have the same indexing.
  140.       local
  141.          line, column, depth, n: INTEGER;
  142.       do
  143.          make(model.upper - model.lower + 1,
  144.               model.first.upper - model.first.lower + 1,
  145.               model.first.first.upper - model.first.first.lower + 1);
  146.      from
  147.         line := model.lower;
  148.      until
  149.         line > model.upper
  150.      loop
  151.         from
  152.            column := model.first.lower
  153.         until
  154.            column > model.first.upper
  155.         loop
  156.                from
  157.                   depth := model.first.first.lower
  158.                until
  159.                   depth > model.first.first.upper
  160.                loop
  161.                   storage.put(model.item(line).item(column).item(depth),n);
  162.                   n := n + 1;
  163.                   depth := depth + 1;
  164.                end;
  165.            column := column + 1;
  166.         end;
  167.         line := line + 1;
  168.      end;
  169.       ensure
  170.          line_maximum = model.upper - model.lower;
  171.          column_maximum = model.first.upper - model.first.lower;
  172.          depth_maximum = model.first.first.upper - model.first.first.lower
  173.       end;
  174.  
  175.  
  176. feature -- Implementation of others feature from COLLECTION3 :
  177.  
  178.    item(line, column, depth: INTEGER): E is
  179.       do
  180.          Result := storage.item(line * count2x3 + column * count3 + depth);
  181.       end;
  182.    
  183.    put(x: like item; line, column, depth: INTEGER) is
  184.       do
  185.          storage.put(x,line * count2x3 + column * count3 + depth);
  186.       end;
  187.    
  188.    force(element: like item; line, column, depth : INTEGER) is
  189.       do
  190.          if not valid_index(line, column, depth) then
  191.             resize(line.max(upper1) + 1,
  192.                    column.max(upper2) + 1,
  193.                    depth.max(upper3) + 1);
  194.      end;
  195.          put(element,line,column,depth);
  196.       end;
  197.  
  198.    copy(other: like Current) is
  199.       do
  200.      count1 := other.count1;
  201.      upper1 := count1 - 1;
  202.      count2 := other.count2;
  203.      upper2 := count2 - 1;
  204.          count3 := other.count3;
  205.          count2x3 := count2 * count3;
  206.          upper3 := count3 - 1;
  207.          count := count1 * count2x3;
  208.      if capacity < count then
  209.         capacity := count;
  210.         storage := storage.calloc(capacity);
  211.      end;
  212.      storage.copy_from(other.storage, count - 1);
  213.       end;
  214.    
  215.    is_equal(other: like Current): BOOLEAN is
  216.       do
  217.      if other = Current then
  218.         Result := true;
  219.      elseif upper1 /= other.upper1 then
  220.      elseif upper2 /= other.upper2 then
  221.          elseif upper3 /= other.upper3 then
  222.      else
  223.         Result := storage.memcmp(other.storage,count);
  224.      end;
  225.       end;
  226.  
  227.    sub_collection3(line_min, line_max, column_min, column_max,
  228.                    depth_min, depth_max: INTEGER): like Current is
  229.       local
  230.          i, j, k, n: INTEGER;
  231.       do
  232.          !!Result.make(line_max - line_min + 1,
  233.                        column_max - column_min + 1,
  234.                        depth_max - depth_min + 1);
  235.      from
  236.             i := line_min;
  237.         k := 0;
  238.      until
  239.         i > line_max
  240.      loop
  241.         from
  242.                j := column_min;
  243.         until
  244.            j > column_max
  245.         loop
  246.                from
  247.                   k := depth_min;
  248.                until
  249.                   k > depth_max
  250.                loop
  251.                   Result.storage.put(item(i,j,k),n);
  252.                   n := n + 1;
  253.                   k := k + 1;
  254.                end;
  255.                j := j + 1;
  256.         end;
  257.         i := i + 1;
  258.      end;
  259.       ensure
  260.          Result.upper1 = line_max - line_min;
  261.          Result.upper2 = column_max - column_min;
  262.          Result.upper3 = depth_max - depth_min;
  263.       end;
  264.  
  265. feature -- Writing :
  266.    
  267.    set_all_with(x: E) is
  268.      --  All element are set with the value x.
  269.       do
  270.      storage.set_all_with(x,count - 1)
  271.       end;
  272.  
  273.    all_default: BOOLEAN is
  274.       do
  275.      result := storage.all_default(count - 1);
  276.       end;
  277.    
  278.    slice(l1,up1,l2,up2,l3,up3: INTEGER): like Current is
  279.      -- Create a new collection initialized with elements of
  280.      -- range `low'..`up'. Result has the same dynamic type 
  281.      -- as Current collection.
  282.       local
  283.          line, column, depth : INTEGER;
  284.      k : INTEGER;
  285.       do
  286.      from 
  287.             !!Result.make((up1 - l1) + 1,(up2 - l2) + 1,(up3 - l3) + 1);
  288.             line := l1;
  289.      until 
  290.             line > up1
  291.      loop 
  292.         from 
  293.                column := l2;
  294.         until 
  295.                column > up2
  296.         loop 
  297.                from 
  298.                   depth := l3;
  299.                until 
  300.                   depth > up3
  301.                loop 
  302.                   Result.put(item(line,column,depth),
  303.                              line - l1,
  304.                              column - l2,
  305.                              depth - l3);
  306.                   depth := depth + 1;
  307.                end;
  308.                column := column + 1;
  309.         end; 
  310.             line := line + 1;
  311.      end; 
  312.       end; -- slice
  313.    
  314.    set_slice(element: like item;  l1,up1,l2,up2,l3,up3: INTEGER) is
  315.          -- Set all the elements in the 
  316.          -- range [(l1,up1),(l2,up2),(l3,up3)] of
  317.          -- Current with the element 'element'.
  318.       local
  319.          i,j,k : INTEGER;
  320.       do
  321.      from 
  322.             i := l1 * count2x3;
  323.          until 
  324.             i > up1 * count2x3
  325.          loop 
  326.             from 
  327.                j := l2 * count3;
  328.             until 
  329.                j > up2 * count3
  330.             loop 
  331.                from 
  332.                   k := l3;
  333.                until 
  334.                   k > up3
  335.                loop 
  336.                   storage.put(element,i + j + k);
  337.                   k := k + 1;
  338.                end;
  339.                j := j + count3;
  340.             end; 
  341.             i := i + count2x3;
  342.          end; 
  343.       end;
  344.  
  345.    swap(line1, column1, depth1, line2, column2, depth2 : INTEGER) is
  346.       local
  347.      tmp: like item;
  348.          c3, c2x3, index1, index2 : INTEGER
  349.       do
  350.      c3 := count3;
  351.          c2x3 := count2x3;
  352.          index1 := line1 * c2x3 + column1 * c3 + depth1;
  353.          index2 := line2 * c2x3 + column2 * c3 + depth2;
  354.      tmp := storage.item( index1);     
  355.          storage.put(storage.item(index2), index1);
  356.      storage.put(tmp,index2);
  357.       end
  358.    
  359. feature -- Looking and comparison :
  360.  
  361.    nb_occurrences(elt: E): INTEGER is
  362.      -- Number of occurrences using `equal'.
  363.          -- See also `fast_nb_occurrences' to choose
  364.      -- the apropriate one.
  365.       do
  366.          Result := storage.nb_occurrences(elt,count - 1);
  367.       end;
  368.       
  369.    fast_nb_occurrences(elt: E): INTEGER is
  370.      -- Number of occurrences using `='.
  371.       do
  372.      Result := storage.fast_nb_occurrences(elt,count - 1);
  373.       end;
  374.  
  375. feature -- Resizing :
  376.  
  377.    resize(new_count1 , new_count2, new_count3: INTEGER) is
  378.       require
  379.      new_count1 > 0;
  380.      new_count2 > 0;
  381.          new_count3 > 0
  382.       local
  383.      tmp: like Current;
  384.          l, c, d: INTEGER;
  385.       do
  386.          !!tmp.make(new_count1, new_count2, new_count3);
  387.          -- It may be possible to avoid this creation when :
  388.      --    new `capacity' <= old `capacity'
  389.      from
  390.         l := line_maximum;
  391.      until
  392.         l < 0
  393.      loop
  394.         from
  395.            c := column_maximum;
  396.         until
  397.            c < 0
  398.         loop
  399.                from
  400.                   d := depth_maximum;
  401.                until
  402.                   d < 0
  403.                loop
  404.                   if tmp.valid_index(l,c,d) then
  405.                      tmp.put(item(l,c,d),l,c,d);
  406.                   end;
  407.                   d := d - 1;
  408.            end;
  409.            c := c - 1;
  410.         end;
  411.         l := l - 1;
  412.      end;
  413.      standard_copy(tmp);
  414.       ensure
  415.      upper1 = new_count1 - 1;
  416.      count1 = new_count1;     
  417.      upper2 = new_count2 - 1;
  418.      count2 = new_count2;
  419.          upper3 = new_count3 - 1;
  420.          count3 = new_count3;
  421.          count = new_count1 * new_count2 * new_count3
  422.       end;
  423.  
  424. feature -- Looking and Searching :
  425.  
  426.    has(x: like item): BOOLEAN is
  427.      -- Look for `x' using `equal' for comparison.      
  428.       do
  429.      Result := storage.index_of(x,count-1) <= (count-1);
  430.       end;  -- has
  431.    
  432.    fast_has(x: like item): BOOLEAN is
  433.      -- Same as `has' but use `=' for comparison      
  434.       do
  435.      Result := storage.fast_index_of(x,count - 1) <= (count - 1);
  436.       end; -- fast_has
  437.  
  438. feature -- Other features :
  439.    
  440.    replace_all(old_value, new_value: like item) is
  441.       do
  442.      storage.replace_all(old_value,new_value,count - 1);
  443.       end;
  444.      
  445.    fast_replace_all(old_value, new_value: like item) is
  446.       do
  447.      storage.fast_replace_all(old_value,new_value,count - 1);
  448.       end;
  449.  
  450. feature {COLLECTION3}
  451.  
  452.    same_as(other: COLLECTION3[E]): BOOLEAN is
  453.       do
  454.          Result := other.same_as_fixed_array3(Current);
  455.       end;
  456.  
  457.    same_as_array3(other: ARRAY3[E]): BOOLEAN is
  458.       do
  459.      Result := standard_same_as(other);
  460.       end;
  461.  
  462.    same_as_fixed_array3(other: FIXED_ARRAY3[E]): BOOLEAN is
  463.       do
  464.      Result := standard_same_as(other);
  465.       end;
  466.  
  467. invariant
  468.  
  469.    count1 = upper1 + 1;
  470.    
  471.    count2 = upper2 + 1;
  472.  
  473.    count3 = upper3 + 1;
  474.  
  475.    count = count1 * count2 * count3;
  476.  
  477.    count2x3 = count2 * count3;
  478.  
  479.    capacity >= count;
  480.  
  481. end -- FIXED_ARRAY3[E]
  482.